/** 
 * Archivo de encabezamiento: contrato con el TAD Lista Lineal
 * simplemente encadenada ordenada, sin repeticiones y con header
*/

#ifndef _LISTALINEAL_ORDENADA_CONHEADER_SINREPETICIONES_H
#define _LISTALINEAL_ORDENADA_CONHEADER_SINREPETICIONES_H
/**
 * El siguiente tipo define el tipo de datos que manipula el TAD lista
 * con header. Los elementos son direcciones previamente alocadas por el
 * usuario (heap o stack). NO permite manipular constantes.
*/
typedef void* listElementT;

/** 
 * El siguiente tipo define el TAD Lista. Se lo define como puntero a
 * "cierta estructura" para ocultar la real representacion de la misma
*/
typedef struct listCDT *listADT;

/** Operaciones con las que se puede acceder al TAD */

/** 
 * Funcion: NewList
 * Uso: lista= NewList( myFuncion );
 * -------------------------------------------------------------------
 * Descripcin: Inicializa la lista y setea la funcin de
 * comparacin para sus elementos. Dicha funcin
 * compara dos elementos de tipo listElementT
 * y debe devolver un nmero negativo si el primer
 * argumento debe aparecer antes que el segundo,
 * un nmero positivo si debe aparecer despus 
 * 0 si se trata del mismo elemento.
 * Usarla una sola vez antes de empezar
 * a usar el resto de las operaciones.
 * Devuelve NULL si no se pudo alocar memoria.
 * -------------------------------------------------------------------
 * Precondicion: Funcin distinta de NULL
 * Postcondicion: Lista creada
*/
listADT NewList(int (*fn)( listElementT elem1, listElementT elem2) );

/** 
 * Funcion: Insert
 * Uso: double nro= 12.3;
 * Insert( lista, &nro );
 * -------------------------------------------------------------------
 * Descripcin: Inserta un elemento en la lista ordenada,
 * usando la funcin de comparacin seteada en
 * la creacin de la lista. El usuario debe
 * proporcionar la direccin del elemento.
 * Si el elemento ya exista, lo ignora.
 * Si hay problemas en la alocacin de memoria
 * finaliza la aplicacin.
 * -------------------------------------------------------------------
 * Precondicion: Lista que sea valida, previamente creada
 * Postcondicion: Lista con el nuevo elemento,
 * si no estaba repetido.
*/
int Insert(listADT list, listElementT element);

/** 
 * Funcion: Delete
 * Uso: double nro= 12.3;
 * if ( Delete(lista, &nro ) ) .
 * -------------------------------------------------------------------
 * Descripcin: Elimina el elemento de la lista ordenada,
 * usando la funcin de comparacin seteada en la
 * creacin de la lista. Se proporciona la
 * direccion del elemento. Si el elemento
 * no exista devuelve 0, caso contrario 1
 * -------------------------------------------------------------------
 * Precondicion: Lista que sea valida, previamente creada
 * Postcondicion: Lista sin el elemento
*/
int Delete(listADT list, listElementT element);

/** 
 * Funcion: ListIsEmpty
 * Uso: if ( ListIsEmpty( lista ) ...
 * -------------------------------------------------------------------
 * Descripcin: Devuelve 1 si la lista est vaca o
 * cero en caso contrario
 * -------------------------------------------------------------------
 * Precondicion: Lista que sea valida, previamente creada
 * Postcondicion: - (lista invariante).
*/
int ListIsEmpty(listADT list);

/** 
 * Funcion: ElementBelongs
 * Uso: double nro= 12.3;
 * if ( ElementBelongs( lista, &nro ))...
 * -------------------------------------------------------------------
 * Descripcin: Devuelve 1 si el elemento pertenece a la lista
 * o cero en caso contrario
 * -------------------------------------------------------------------
 * Precondicion: Lista previamente creada
 * Postcondicion: - (lista invariante).
*/
int ElementBelongs(listADT lista, listElementT element);

/** 
 * Funcion: SetBegin
 * Uso: SetBegin( lista )
 * -------------------------------------------------------------------
 * Descripcin: Permite comenzar a recorrer la lista desde
 * el comienzo. Se usa conjuntamente con GetDato
 * -------------------------------------------------------------------
 * Precondicion: Lista previamente creada
 * Postcondicion: Proximo nodo a acceder con GetDato: el primero.
*/
void SetBegin(listADT list);

/** 
 * Funcion: RewindList
 * Uso:  listElement=GetDato(lista);
 *	 RewindList( lista );
 *	 listElement=GetDato(lista);
 *	 
 * -------------------------------------------------------------------
 * Descripcion: Permite volver al elemento anterior en caso que se
 * haya cometido algun olvido. Sólo permirte ir una vez atras, tras
 * sucesivas llamadas de RewindList se devuelve el mismo elemento si
 * se invoca GetDato. Para ir al principio de la lista usar SetBegin.
 * Se usa conjuntamente con GetDato.
 * -------------------------------------------------------------------
 * Precondicion: Lista previamente creada.
 * Postcondicion: Proximo nodo a acceder con GetDato: el mismo que en
 * la llamada anterior al RewindList.
*/
void RewindList(listADT list);

/**
 * Funcion: ListTail
 * Uso: listADT lista;
 * double *nro;
 * ...
 * SetBegin(lista);
 * while ( (nro= GetDato(list)) != NULL )
 * printf("%g\n", *nro );
 * -------------------------------------------------------------------
 * Descripcin: Es de consulta. Sirve para iterar por la
 * lista, la cual sigue intacta (invariante).
 * Devuelve NULL cuando se intenta avanzar y
 * se esta sobre el ltimo nodo.
 * Luego de la invocacin, el proximo GetDato
 * ser el siguiente elemento y as sucesivamente.
 * -------------------------------------------------------------------
 * Precondicion: Lista no vaca
 * Postcondicion: - (lista invariante).
*/
listElementT GetDato(listADT list);

/** 
 * Funcion: FreeList
 * Uso: FreeList( lista );
 * -------------------------------------------------------------------
 * Descripcin: Destruye la lista, liberando recursos alocados.
 * Usarla una sola vez al finalizar el uso
 * de la lista. Despues no volver a
 * invocar operaciones sobre la lista.
 * -------------------------------------------------------------------
 * Precondicion: Lista que sea valida.
 * Postcondicion: -
*/
void FreeList(listADT lista);

void FreeDeepList(listADT list, void (*FreeElement)(void * ));
int ListLength(listADT list);
void * GetNthElement( listADT list, int n);
int PrintList(listADT list, void (*print)(listElementT));

#endif
